Skip to content

Add route middleware: auth, Throttle, ApiKey, IP filtering, HTTPS, CSRF, Honeypot and signed URLs - #74

Merged
lmajano merged 4 commits into
developmentfrom
claude/funny-mendel-eeim2l
Oct 8, 2026
Merged

lmajano merged 4 commits into
developmentfrom
claude/funny-mendel-eeim2l

Conversation

@lmajano

@lmajano lmajano commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds ready-made ColdBox route middleware so a route or a group can be secured where it is declared, without firewall rules. Parameters travel in the route meta() because a router file loads before modules.

Authentication middleware

route( "/account" ).middleware( "Authenticated@cbsecurity" ).to( "account.index" )

route( "/admin" )
    .middleware( "Authorized@cbsecurity" )
    .meta( { permissions : "ADMIN" } )
    .to( "admin.index" )
  • Authenticated@cbsecurity: logged in (ignores meta)
  • Authorized@cbsecurity: logged in and satisfying route meta permissions, roles and mode (any, all, none)
  • JwtAuth@cbsecurity / BasicAuth@cbsecurity: like Authorized, through those validators
  • Guard: base class for custom middleware

Denied requests go through the firewall's invalid access flow (redirect, override, block, module overrides, interception points, logging). Security gains public validateAccess() and processInvalidAccess(); the annotation path shares processInvalidAccess() with no behavior change.

Abuse protection middleware (new in this update)

They answer denied requests directly with a JSON error and status code. Defaults live in the new middleware and signedUrls module settings, every value can be overridden per route.

ID Does Route meta()
Throttle@cbsecurity Rate limit, 429 + Retry-After, named or inline limiters, any CacheBox cache (default default) throttle
ApiKey@cbsecurity x-api-key header then apiKey request key (both configurable), keys or a validator service apiKeys, apiKeyHeader, apiKeyParam
AllowedIPs@cbsecurity / DenyIPs@cbsecurity IPv4, IPv6 and CIDR, X-Forwarded-For only from trustedProxies allowedIps, denyIps
EnsureHttps@cbsecurity 301 for GET/HEAD, 403 for other methods redirectToHttps
VerifyCsrf@cbsecurity cbcsrf token on unsafe methods csrfKey
Honeypot@cbsecurity Hidden trap field, silent 200 or 422 honeypotField, honeypotSilent
Signed@cbsecurity Only valid, unexpired signed URLs none

New models: RateLimiter@cbsecurity (cache backed fixed window) and UrlSigner@cbsecurity (HMAC-SHA256 over path and query, optional expiration). New mixins: signedRoute(), signedUrl(), hasValidSignature(). A missing IP list or API keys throws cbsecurity.MiddlewareMisconfigured, a missing signing secret throws cbsecurity.SigningSecretMissing.

Requirements

Type of change

Checklist

  • cfformat applied to my files
  • I have commented my code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my feature works
  • New and existing tests pass locally with my changes

Testing

BoxLang 1.18, TestBox 7.1, against the companion ColdBox changes: 212 passed, 105 of them in the two middleware specs (MiddlewareSpec 31, SecurityMiddlewareSpec 74). The 1 failure and 15 errors are pre-existing and all say "No default datasource" (this sandbox has no MySQL, JWT DB storage specs). Route specs skip themselves through feature detection on ColdBox without 8.3 behavior. I could not run Adobe, Lucee or ColdBox 7 locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01E8yy4oK5vnaVucmYLg4UtY

Secure a route or a group where it is declared, with no firewall rules:

- Authenticated@cbsecurity: the user must be logged in
- Authorized@cbsecurity: logged in and satisfying the `permissions`, `roles`
  and `mode` (any|all|none) declared in the route `meta()`
- JwtAuth@cbsecurity and BasicAuth@cbsecurity: Authorized, authenticating
  through the JWT or Basic validators
- Guard: the base class for custom middleware

Denied requests go through the firewall's invalid access flow, so redirect,
override and block actions, module overrides, interception points and logging
behave exactly like a firewall rule or annotation. The Security interceptor
gains public validateAccess() and processInvalidAccess() methods for this; the
annotation path now shares processInvalidAccess() with no behavior change.

The route specs run only when the installed ColdBox can run route middleware in
execute() and group meta (8.3+); the Guard specs run everywhere.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8yy4oK5vnaVucmYLg4UtY
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

lucee@5 ColdBox ^8.0.0 Test Results

  1 files  ±  0    9 suites  +2   10s ⏱️ +3s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

lucee@6 ColdBox ^8.0.0 Test Results

0 tests   - 123   0 ✅  - 123   0s ⏱️ -6s
0 suites  -   7   0 💤 ±  0 
0 files    -   1   0 ❌ ±  0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

boxlang-cfml@1 ColdBox be Test Results

228 tests  +105   228 ✅ +105   16s ⏱️ +10s
  9 suites +  2     0 💤 ±  0 
  1 files   ±  0     0 ❌ ±  0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

lucee@6 ColdBox ^7.0.0 Test Results

  1 files  ±  0    9 suites  +2   10s ⏱️ +4s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

lucee@5 ColdBox ^7.0.0 Test Results

  1 files  ±  0    9 suites  +2   11s ⏱️ +4s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

lucee@6 ColdBox be Test Results

228 tests  +105   228 ✅ +105   14s ⏱️ +8s
  9 suites +  2     0 💤 ±  0 
  1 files   ±  0     0 ❌ ±  0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

boxlang-cfml@1 ColdBox 8 Test Results

  1 files  +  1    9 suites  +9   12s ⏱️ +12s
177 tests +177  177 ✅ +177   0 💤 ± 0  0 ❌ ±0 
228 runs  +228  177 ✅ +177  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

boxlang-cfml@1 ColdBox ^7.0.0 Test Results

  1 files  ±  0    9 suites  +2   12s ⏱️ +5s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

boxlang-cfml@1 ColdBox ^8.0.0 Test Results

  1 files  ±  0    9 suites  +2   12s ⏱️ +8s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

boxlang-cfml@be ColdBox 8 Test Results

  1 files  ±  0    9 suites  +2   12s ⏱️ +6s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

adobe@2025 ColdBox ^8.0.0 Test Results

  1 files  ±  0    9 suites  +2   9s ⏱️ +3s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

adobe@2023 ColdBox ^8.0.0 Test Results

  1 files  ±  0    9 suites  +2   11s ⏱️ +5s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

adobe@2023 ColdBox be Test Results

228 tests  +105   228 ✅ +105   14s ⏱️ +8s
  9 suites +  2     0 💤 ±  0 
  1 files   ±  0     0 ❌ ±  0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

adobe@2023 ColdBox ^7.0.0 Test Results

  1 files  ±  0    9 suites  +2   8s ⏱️ +2s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

adobe@2025 ColdBox ^7.0.0 Test Results

  1 files  ±  0    9 suites  +2   11s ⏱️ +6s
177 tests + 54  177 ✅ +54   0 💤 ± 0  0 ❌ ±0 
228 runs  +105  177 ✅ +54  51 💤 +51  0 ❌ ±0 

Results for commit 8534bd8. ± Comparison against base commit a890b0c.

♻️ This comment has been updated with latest results.

lmajano commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

CI status

  • All test suites are green (Lucee 5 and 6, ColdBox ^7, ^8 and BE): 139 passed, 0 failed, 15 skipped. The 15 skips are the route specs, which skip themselves unless the installed ColdBox is 8.3+.
  • Checks Source Code Formatting is red, and the only file it flags is my new test-harness/tests/specs/integration/MiddlewareSpec.cfc. I could not reproduce the CI formatter locally: cfformat 0.19 to 0.21 report the file as clean and 0.22 formats it differently, and none of the versions I tried (0.17 to 0.22) flag it the way CI does.
  • What unblocks it: run box run-script format with the project's formatter and commit the result for that one file. The snapshot workflow also auto-formats on development, so this self-heals after merge. I did not want to push guessed formatting changes.

Generated by Claude Code

…srf, Honeypot and Signed route middleware

Adds RateLimiter and UrlSigner models, signedRoute(), signedUrl() and
hasValidSignature() mixins, middleware and signedUrls settings, and specs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8yy4oK5vnaVucmYLg4UtY
@lmajano lmajano changed the title Add route middleware: Authenticated, Authorized, JwtAuth, BasicAuth Add route middleware: auth, Throttle, ApiKey, IP filtering, HTTPS, CSRF, Honeypot and signed URLs Oct 8, 2026

lmajano commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

CI note on head 113d3fe: Checks Source Code Formatting fails on models/middleware/Throttle.cfc, test-harness/tests/specs/integration/SecurityMiddlewareSpec.cfc and test-harness/tests/specs/integration/MiddlewareSpec.cfc. The check runs cfformat from CommandBox 5.4.2 (cfml-ci-tools 1.0.6), which formats differently from the cfformat 0.21.0 I can install here, and I can't fetch the CI version. I formatted every new file locally with 0.21.0 and it reports clean there, so I can't tell what CI wants without guessing, and a guess would churn the files. All test jobs are separate from this check. A maintainer can run box run-script format with the CI toolchain and push the result, or the snapshot workflow's Apply cfformat changes step will do it after merge.


Generated by Claude Code

claude added 2 commits October 8, 2026 18:10
…ut route middleware

- Replace elvis with struct literal operands, which Adobe ColdFusion misparses
- Build signedRoute() with loops instead of closures
- Skip the ApiKey route specs when the installed ColdBox cannot run route middleware

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8yy4oK5vnaVucmYLg4UtY
…operator

Adobe ColdFusion ignores a false value on the left of ?:, so a route's
honeypotSilent = false fell back to the default. Add getMetaValue() and use it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E8yy4oK5vnaVucmYLg4UtY
@lmajano
lmajano merged commit 1ac4cb3 into development Oct 8, 2026
45 of 48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants